#include "XXactivityIndicatorView.h"
#include <QPainter>
#include "../XXqtDefine.h"

const char * const XXactivityIndicatorView::kItemPadding = "itemPadding";
const char * const XXactivityIndicatorView::kItemMargin = "itemMargin";
const char * const XXactivityIndicatorView::kItemSize = "itemSize";
const char * const XXactivityIndicatorView::kItemCount = "itemCount";
const char * const XXactivityIndicatorView::kActiveItemCount = "activeItemCount";

const char * const XXactivityIndicatorView::kNormalColor = "normalColor";
const char * const XXactivityIndicatorView::kActiveColor = "activeColor";
const char * const XXactivityIndicatorView::kBgColor = "bgColor";
const char * const XXactivityIndicatorView::kBgRadius = "bgRadius";
const char * const XXactivityIndicatorView::kCenterAt = "centerAt";

#define IsNumber(x) (x.type()==QVariant::Int||x.type()==QVariant::Double)
#define IsSize(x) (x.type()==QVariant::Size||x.type()==QVariant::SizeF)

XXactivityIndicatorView::XXactivityIndicatorView(QWidget *parent)
    : QWidget(parent)
    , _itemPadding(10)
    , _itemMargin(10)
    , _itemSize(4,15)
    , _itemCount(8)
    , _activeItemCount(4)
    , _normalColor(153, 153, 153)
    , _activeColor(Qt::white)
    , _bgColor(0,0,0,127)
    , _bgRadius(20.0)
    , _centerAt(nullptr)
    , _timerID(0)
    , _activeIndex(0)
    , _isFullAtParent(false)
    , _willCancelBlock(nullptr)
    , _cancelButton(nullptr)
{
    this->setAttribute(Qt::WA_StyledBackground);
    this->setMinimumSize(100,100);
    this->setMaximumSize(100,100);
    QWidget::hide();
}
XXactivityIndicatorView::~XXactivityIndicatorView(){
    stop();
}

void XXactivityIndicatorView::config(const QVariantMap &param){
    if(param.contains(kItemPadding) && param[kItemPadding].canConvert<qreal>()){
        _itemPadding = param[kItemPadding].toDouble();
    }
    if(param.contains(kItemMargin) && param[kItemMargin].canConvert<qreal>()){
        _itemMargin = param[kItemMargin].toDouble();
    }
    if(param.contains(kItemSize) && param[kItemSize].canConvert<QSizeF>()){
        _itemSize = param[kItemSize].toSizeF();
    }
    if(param.contains(kItemCount) && param[kItemCount].canConvert<int>()){
        _itemCount = param[kItemCount].toInt();
    }
    if(param.contains(kActiveItemCount) && param[kActiveItemCount].canConvert<int>()){
        _activeItemCount = param[kActiveItemCount].toInt();
    }

    if(param.contains(kNormalColor) && param[kNormalColor].canConvert<QColor>()){
        _normalColor = param[kNormalColor].value<QColor>();
    }
    if(param.contains(kActiveColor) && param[kActiveColor].canConvert<QColor>()){
        _activeColor = param[kActiveColor].value<QColor>();
    }
    if(param.contains(kBgColor) && param[kBgColor].canConvert<QColor>()){
        _bgColor = param[kBgColor].value<QColor>();
    }
    if(param.contains(kCenterAt) && param[kCenterAt].canConvert<void*>()){
        _centerAt = static_cast<QWidget*>(param[kCenterAt].value<void*>());
    }
}
void XXactivityIndicatorView::configItem(int margin, int padding, QSize size, int count, int activeCount, QColor normal, QColor active){
    if(margin>=0) _itemMargin = margin;
    if(padding>=0) _itemPadding = padding;
    if(!size.isNull()) _itemSize = size;
    if(count>=0) _itemCount = count;
    if(activeCount>=0) _activeItemCount = activeCount;

    if(normal.isValid()) _normalColor = normal;
    if(active.isValid()) _activeColor = active;
}
void XXactivityIndicatorView::configBackgroundColor(QColor color, qreal radius, QWidget *centerAt){
    if(color.isValid()) _bgColor = color;
    if(radius>=0) _bgRadius = radius;
    _centerAt = centerAt;
    _centerAt->installEventFilter(this);
}
void XXactivityIndicatorView::configCancel(const QString &title, int height, std::function<bool(void)> block){
    if(!_cancelButton){
        delete _cancelButton;
        _cancelButton = nullptr;
    }
    _willCancelBlock = block;
    if(minimumWidth()==minimumHeight()){
        setMinimumWidth(this->minimumWidth()+height);
        setMaximumWidth(this->maximumWidth()+height);
    }
    setMinimumHeight(this->minimumHeight()+height);
    setMaximumHeight(this->maximumHeight()+height);

    _cancelButton = new QPushButton(this);
    _cancelButton->setText(title);
    _cancelButton->setMinimumHeight(height);
    _cancelButton->setMaximumHeight(height);
    _cancelButton->setFixedHeight(height);
    _cancelButton->setObjectName("pushButton_cancel");
    connect(_cancelButton,&QPushButton::clicked,this,[&]{
        if(_willCancelBlock){
            if(_willCancelBlock())
                hide();
        }
        else{
            hide();
        }
    });
    _cancelButton->setStyleSheet(QString("QPushButton{"
                                         "  background:%1;"
                                         "  border:none;"
                                         "  border-bottom-right-radius:%2px;"
                                         "  border-bottom-left-radius:%2px;"
                                         "  color:white;"
                                         "  font-family: Microsoft YaHei;"
                                         "}"
                                         "QPushButton:hover{"
                                         "  background: %3;"
                                         "}")
                                 .arg("transparent")
                                 .arg(_bgRadius)
                                 .arg("#1fffffff"));
}
void XXactivityIndicatorView::configWindowModal(){
    XX_MODAL_WINDOW(this);
    setWindowFlag(Qt::FramelessWindowHint);
    setAttribute(Qt::WA_TranslucentBackground, true);
}

void XXactivityIndicatorView::setWillCancelBlock(std::function<bool(void)> block){
    _willCancelBlock = block;
}
void XXactivityIndicatorView::show(){
    if(nullptr != parentWidget()){
        if(_isFullAtParent){
            this->setGeometry(parentWidget()->geometry());
        }
        else{
            QPoint center = parentWidget()->rect().center();
            QPoint leftTop(center.x()-this->size().width()/2,center.y()-this->size().height()/2);
            if(this->windowFlags()&Qt::Window){
                QPoint gLeftTop = parentWidget()->mapToGlobal(leftTop);
                move(gLeftTop);
            }
            else{
                move(leftTop);
            }
        }
    }
    else if(nullptr != _centerAt){
        if(_isFullAtParent){
            this->setGeometry(_centerAt->geometry());
        }
        else{
            QPoint center = _centerAt->rect().center();
            QPoint leftTop(center.x()-this->size().width()/2,center.y()-this->size().height()/2);
            QPoint gLeftTop = _centerAt->mapToGlobal(leftTop);
            move(gLeftTop);
        }
    }
    else{

    }

    if(_cancelButton){
        QRect rect = _cancelButton->geometry();
        rect.setWidth(this->width());
        rect.setX(0);
        rect.setY(this->height()-rect.height());
        _cancelButton->setGeometry(rect);
    }

    start();
    QWidget::show();
}
void XXactivityIndicatorView::hide(){
    QWidget::hide();
    stop();
}

//QSize XXactivityIndicatorView::sizeHint() const{
//    return QSize(100,100);
//}
bool XXactivityIndicatorView::eventFilter(QObject *watcher, QEvent *event){
    if(watcher==_centerAt && event->type()==QEvent::Resize){
        updatePosition();
    }
    return QWidget::eventFilter(watcher,event);
}
void XXactivityIndicatorView::paintEvent(QPaintEvent *event){
    Q_UNUSED(event);
    //QWidget::paintEvent(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing,true);

    // 绘制一下背景
    painter.setPen(Qt::NoPen);
    painter.setBrush(_bgColor);
    painter.drawRoundedRect(this->rect(),_bgRadius,_bgRadius);

    // 移动到中心区域
    qreal bgHeight;
    if(false && _cancelButton){
        bgHeight = this->rect().size().height()-_cancelButton->minimumHeight();
        QRect rect = this->rect();
        rect.setHeight(static_cast<int>(bgHeight));
        painter.translate(rect.center());
    }
    else{
        bgHeight = this->rect().size().height();
        painter.translate(this->rect().center());
    }

    // 绘制基本的item
    qreal itemWidth = _itemSize.width();
    qreal itemHeight = _itemSize.height() > 0 ? _itemSize.height() : bgHeight*0.5-_itemPadding-_itemMargin;

    painter.setPen(Qt::NoPen);
    painter.setBrush(_normalColor);
    QRectF itemRect(-itemWidth*0.5,-_itemPadding-itemHeight,itemWidth,itemHeight);
    qreal step = 360.0/_itemCount;
    for (int index=0; index<_itemCount; index++) {
        painter.rotate(step);
        painter.drawRect(itemRect);
    }

    // 绘制激活项
    qreal startAlpha = 0.2;
    qreal endAlpha = 1;
    qreal stepAlpha = (endAlpha-startAlpha)/(_activeItemCount-1);
    for (int index=0; index<_activeItemCount; index++) {
        if(0 == index){
            painter.rotate(step*(_activeIndex-3));
        }
        else{
            painter.rotate(step);
        }

        QColor color = _activeColor;
        color.setAlphaF(startAlpha + index*stepAlpha);
        painter.setBrush(color);
        painter.drawRect(itemRect);
    }
}
void XXactivityIndicatorView::timerEvent(QTimerEvent *event){
    if(_timerID > 0 && event->timerId() == _timerID){
        if(++_activeIndex >=_itemCount){
            _activeIndex = 0;
        }
        update();
    }
    QWidget::timerEvent(event);
}

void XXactivityIndicatorView::start(){
    if(_timerID>0){
        return;
    }
    _timerID = startTimer(40);
    _activeIndex = 0;
}
void XXactivityIndicatorView::stop(){
    if(_timerID<=0){
        return;
    }
    killTimer(_timerID);
    _timerID = 0;
    _activeIndex = 0;
}
void XXactivityIndicatorView::updatePosition(){
    QPoint center = parentWidget()->rect().center();
    QPoint leftTop(center.x()-this->size().width()/2,center.y()-this->size().height()/2);
    if(this->windowFlags()&Qt::Window){
        QPoint gLeftTop = parentWidget()->mapToGlobal(leftTop);
        move(gLeftTop);
    }
    else{
        move(leftTop);
    }
}
